package com.square.service.common.aop;

import com.square.service.common.annotation.Log;
import com.square.service.common.utils.AopUtil;
import com.square.service.common.utils.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author : wangsu
 * @date : 2021/11/17 10:30
 * @description : 操作日志注解切面通知
 */
@Slf4j
@Aspect
@Component
@Order(10)
public class LogAspect {

    @Pointcut("@annotation(com.square.service.common.annotation.Log)")
    public void pointCut() {
    }

    //环绕通知抛出异常后不执行point.proceed()以下代码
    //由后置异常通知捕获
    //可借此实现执行时间的记录，后置异常通知无法记录执行时间

    /**
     * 环绕通知
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint point) throws Throwable {
        Object res = point.proceed();
        log.info("=============================环绕通知:" + res.toString());
        return res;
    }

    /**
     * 后置通知
     *
     * @param point
     * @return
     */
    @AfterReturning(value = "pointCut()", returning = "jsonResult")
    public void doAfterReturning(JoinPoint point, Object jsonResult) throws Throwable {
        processPoint(point, null, jsonResult);
    }


    /**
     * 异常通知
     *
     * @param point
     * @param e
     */
    @AfterThrowing(value = "pointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint point, Exception e) throws Throwable {
        processPoint(point, e, null);
    }

    /**
     * 处理通知
     *
     * @param point
     * @param e
     * @return
     */
    private void processPoint(JoinPoint point, Exception e, Object jsonResult) throws Throwable {
        HttpServletRequest request = SpringContextUtil.getHttpServletRequest();
        String requestMethod = request.getMethod();
        String requestPath = request.getRequestURI().substring(request.getContextPath().length());
        requestPath = AopUtil.filterUrl(requestPath);
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Log l = method.getAnnotation(Log.class);
        String name = l.name();
        log.info("操作日志注解【name】：" + name);
        log.info("操作日志注解【requestPath】：" + requestPath);
        log.info("操作日志注解【requestMethod】：" + requestMethod);
        boolean status;
        if (e != null) {
            log.info("操作日志注解【Exception】：" + requestMethod);
            status = false;
        } else {
            log.info("操作日志注解【jsonResult】：" + jsonResult);
            status = true;

        }
        log.info("操作日志注解【成功状态】：" + status);
    }


}
